package tech.heiming.aps.scheduler.deadline;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import tech.heiming.aps.scheduler.domain.ResourceGroup;
import tech.heiming.aps.scheduler.domain.Shift;

import java.util.*;

/**
 * @author heimingz
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class EmployeeArrangement {
    List<ResourceGroup> employeeGroups;

    /**
     * TODO: 待优化
     *
     * @param targetNum      目标资源数
     * @param resourceGroups 资源组
     * @return 资源安排候选方案
     */
    public static List<EmployeeArrangement> getCandidates(Long targetNum, List<ResourceGroup> resourceGroups) {
        List<EmployeeArrangement> candidates = new LinkedList<>();

        Map<Shift, List<ResourceGroup>> shiftGroups = new HashMap<>();
        for (ResourceGroup group : resourceGroups) {
            if (group.getResources() == null || group.getResources().size() == 0) {
                continue;
            }
            Shift shift = group.getResources().get(0).getShift();
            if (shiftGroups.containsKey(shift)) {
                shiftGroups.get(shift).add(group);
            } else {
                List<ResourceGroup> groups = new ArrayList<>();
                groups.add(group);
                shiftGroups.put(shift, groups);
            }
        }

        for (List<ResourceGroup> groups : shiftGroups.values()) {
            groups.sort(Comparator.comparingLong(ResourceGroup::getAmount).reversed());
            List<ResourceGroup> employeeGroups = new LinkedList<>();
            Long total = 0L;
            for (ResourceGroup group : groups) {
                if (group.getAmount() >= targetNum) {
                    candidates.add(new EmployeeArrangement(Collections.singletonList(group)));
                    continue;
                }
                //TODO
                employeeGroups.add(group);
                total += group.getAmount();
                if (total >= targetNum) {
                    candidates.add(new EmployeeArrangement(employeeGroups));
                    employeeGroups = new LinkedList<>();
                    total = 0L;
                }
            }
        }
        return candidates;
    }
}
